﻿using System;
using System.Collections.Generic;
using System.Text;
using System.Runtime.InteropServices;
using System.Windows.Forms;
using System.Diagnostics;

namespace Walson.Message
{
    /// <summary>
    /// 进程间通信的发送方
    /// </summary>
    public class MessageSender : Form
    {
        [StructLayout(LayoutKind.Sequential)]
        private struct COPYDATASTRUCT
        {
            public IntPtr dwData;
            public UInt32 cbData;
            //[MarshalAs(UnmanagedType.LPStr)]
            public IntPtr lpData;
        }

        [DllImport("User32.dll", EntryPoint = "SendMessage")]
        private static extern int SendMessage(
            int hWnd,                       // 目标窗口的句柄
            int Msg,                        // 消息
            int wParam,                     // 第一个消息参数
            ref COPYDATASTRUCT lParam       // 第二个消息参数
            );

        // 发送数据的委托与事件
        public delegate void SendStringEvent(object sender, uint flag, string payload);
        public delegate void SendBytesEvent(object sender, uint flag, byte[] payload);
        public event SendStringEvent OnSendString;
        public event SendBytesEvent OnSendBytes;

        /// <summary>
        /// 向指定名称的进程发送字符串数据
        /// </summary>
        /// <param name="ProcessName"></param>
        /// <param name="Payload"></param>
        /// <returns></returns>
        public void SendMessage(string ProcessName, string Payload)
        {
            foreach (Process p in Process.GetProcessesByName(ProcessName))
            {
                IntPtr processHandle = p.MainWindowHandle;
                if (processHandle == IntPtr.Zero)
                    continue;
                try
                {
                    byte[] sarr = System.Text.Encoding.Default.GetBytes(Payload);
                    COPYDATASTRUCT cds = new COPYDATASTRUCT();
                    cds.dwData = (IntPtr)0x7000;
                    cds.cbData = (uint)sarr.Length;
                    cds.lpData = Marshal.AllocHGlobal(sarr.Length);
                    Marshal.Copy(sarr, 0, cds.lpData, sarr.Length);
                    SendMessage((int)processHandle, 0x004A, 0, ref cds);
                }
                catch (System.Exception ex)
                {
                    MessageBox.Show(ex.Message);
                }
            }
        }

        /// <summary>
        /// 向指定名称的进程发送字节数据
        /// </summary>
        /// <param name="ProcessName"></param>
        /// <param name="Payload"></param>
        /// <returns></returns>
        public void SendMessage(string ProcessName, byte[] Payload)
        {
            foreach (Process p in Process.GetProcessesByName(ProcessName))
            {
                IntPtr processHandle = p.MainWindowHandle;
                if (processHandle == IntPtr.Zero)
                    continue;
                try
                {
                    COPYDATASTRUCT cds = new COPYDATASTRUCT();
                    cds.dwData = (IntPtr)0x7000;
                    cds.cbData = (uint)Payload.Length;
                    cds.lpData = Marshal.AllocHGlobal(Payload.Length);
                    Marshal.Copy(Payload, 0, cds.lpData, Payload.Length);
                    SendMessage((int)processHandle, 0x004A, 0, ref cds);
                }
                catch (System.Exception ex)
                {
                    MessageBox.Show(ex.Message);
                }
            }
        }

        /// <summary>
        /// 向指定名称的进程发送字符串数据
        /// </summary>
        /// <param name="ProcessName"></param>
        /// <param name="Payload"></param>
        /// <returns></returns>
        public void SendMessage(IntPtr ProcessHandle, string Payload)
        {
            IntPtr processHandle = ProcessHandle;
            if (processHandle == IntPtr.Zero)
                return;
            try
            {
                COPYDATASTRUCT cds = new COPYDATASTRUCT();
                byte[] sarr = System.Text.Encoding.Default.GetBytes(Payload);
                cds.dwData = (IntPtr)0x7000;
                cds.cbData = (uint)sarr.Length;
                cds.lpData = Marshal.AllocHGlobal(sarr.Length);
                Marshal.Copy(sarr, 0, cds.lpData, sarr.Length);
                SendMessage((int)processHandle, 0x004A, 0, ref cds);
            }
            catch (System.Exception ex)
            {
                MessageBox.Show(ex.Message);
            }
        }

        /// <summary>
        /// 向指定名称的进程发送字节数据
        /// </summary>
        /// <param name="ProcessName"></param>
        /// <param name="Payload"></param>
        /// <returns></returns>
        public void SendMessage(IntPtr ProcessHandle, byte[] Payload)
        {
            IntPtr processHandle = ProcessHandle;
            if (processHandle == IntPtr.Zero)
                return;
            try
            {
                COPYDATASTRUCT cds = new COPYDATASTRUCT();
                cds.dwData = (IntPtr)0x7000;
                cds.cbData = (uint)Payload.Length;
                cds.lpData = Marshal.AllocHGlobal(Payload.Length);
                Marshal.Copy(Payload, 0, cds.lpData, Payload.Length);
                SendMessage((int)processHandle, 0x004A, 0, ref cds);
            }
            catch (System.Exception ex)
            {
                MessageBox.Show(ex.Message);
            }
        }
    }

    /// <summary>
    /// 进程间通信的接收方
    /// </summary>
    public class MessageReceiver : Form
    {
        [StructLayout(LayoutKind.Sequential)]
        private struct COPYDATASTRUCT
        {
            public IntPtr dwData;
            public UInt32 cbData;
            //[MarshalAs(UnmanagedType.LPStr)]
            public IntPtr lpData;
        }

        // 接收数据的委托与事件
        public delegate void ReceiveStringEvent(object sender, string payload);
        public delegate void ReceiveBytesEvent(object sender, byte[] payload);
        public event ReceiveStringEvent OnReceiveString;
        public event ReceiveBytesEvent OnReceiveBytes;

        private void thd()
        {
            Application.Run(this);
        }

        public MessageReceiver()
        {
            this.TopLevel = false;
            this.Visible = false;
            System.Threading.Thread t= new System.Threading.Thread(new System.Threading.ThreadStart(thd));
            t.IsBackground = true;
            t.Start();
            IntPtr ha = this.Handle;
            ha.ToInt32();
        }

        protected override void DefWndProc(ref System.Windows.Forms.Message m)
        {
            switch (m.Msg)
            {
                case 0x004A:  // WM_COPYDATA 的消息标识
                    {
                        COPYDATASTRUCT cds = new COPYDATASTRUCT();
                        Type myType = cds.GetType();
                        cds = (COPYDATASTRUCT)m.GetLParam(myType);
                        uint flag = (uint)(cds.dwData);
                        byte[] bt = new byte[cds.cbData];
                        Marshal.Copy(cds.lpData, bt, 0, bt.Length);

                        if (flag <= 0x8000)
                        {// 消息的数据类型，小于 0x8000 的为字符，大于 0x8000 的为非字符
                            if (OnReceiveString != null)
                            {
                                OnReceiveString(this, Encoding.Default.GetString(bt));
                            }
                        }
                        else
                        {
                            if (OnReceiveBytes != null)
                            {
                                OnReceiveBytes(this, bt);
                            }
                        }
                        break;
                    }
                default:
                    {
                        base.DefWndProc(ref m);
                        break;
                    }
            }
        }
    }
}
